home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
363_02
/
opparse.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-15
|
48KB
|
1,132 lines
/***********************************************************************
*
* OPPARSE.C
* Operand Parser for 68000 Assembler
*
* Function: isXreg()
* Parses Index Register specification, inserts the upper byte flags
* (see below) into extension word.
*
* Function: opParse()
* Parses an operand of the 68020 assembly language instruction and
* attempts to recognize its addressing mode. The p argument points to
* the string to be evaluated, and the function returns a pointer to the
* first character beyond the end of the operand.
* The function returns a description of the operands that it parses in
* an opDescriptor structure. The fields of the operand descriptor are
* filled in as appropriate for the mode of the operand that was found:
*
* mode returns the address mode (symbolic values defined in ASM.H)
* data returns the displacement or address or immediate value
* reg returns the address or data register number
* size returns the size of absolute address (WORD or LONG)
* xtenWord returns the indexed operation first extension word. The
* 7 MSBits are filled in by isXreg(), the 9 LSBits - by opparse.
* bfXtenWord bit field extension word
* outDisp returns the outer displacement of an indexed operation
* backRef TRUE if data is the value of an expression that contains only
* constants and backwards references; FALSE otherwise.
* odBackRef TRUE if outer displacement is the value of an expression
* that contains only constants and backward references; FALSE
* otherwise.
*
* The argument errorPtr is used to return an error code via the standard
* mechanism.
*
* Usage: char *opParse(char *p, opDescriptor *d, int *errorPtr)
*
* Author: Paul McKee
* ECE492 North Carolina State University, 10/10/86
*
* Revision: 10/26/87
* Altered the immediate mode case to correctly flag
* constructs such as "#$1000(A5)" as syntax errors.
*
* Modified A.E. Romer. Version 1.0
* 17 March 1991 - converted to ANSI
* 21 March 1991 - .w and .l suffixes allowed in absolute addressing
* May 1991 - isXreg() added.
* Summer 1991 - conversion to 68020 format of indirection
* instruction, index SCALE implementation, addition
* of 68020 specific instructions
*
************************************************************************/
#include <stdio.h>
#include <ctype.h>
#include "asm.h"
extern char pass2;
extern long loc;
#define isTerm(c) (isspace(c) /* operand field terminator */\
|| (c == ',') /* source/destination separator */\
|| c == '{' /* bit field specification start */\
|| c == '\0') /* line terminator */
#define isRegNum(c) ((c >= '0') && (c <= '7'))
char *isXreg(char *p, opDescriptor *d, int *errorPtr)
{
long scale;
if ((p[0] == 'A' || p[0] == 'D') && isRegNum(p[1]))
/* set index register field in the extension word */
{
d->xtenWord |= XREG_NUM(p[1] - '0');
if (p[0] == 'A')
d->xtenWord |= XREG_IS_An;
/* neither size nor scale specified */
if (p[2] == ')' || p[2] == ']' || p[2] ==',')
return p+2; /* Default index register size
* and scale, null displacement */
/* size specified */
else if (p[2] == '.')
{
/* Determine size of index register */
if (p[3] == 'W')
; /* default */
else if (p[3] == 'L')
d->xtenWord |= XSIZE_LONG;
else
{
NEWERROR(*errorPtr, SYNTAX);
return NULL;
}
if (p[4] == ')' || p[4] == ']' || p[4] == ',')
/* no scale specified */
return p+4; /* default scale is 1 */
else if (p[4] == '*') /* scale specified */
{
p = eval(p+5, &scale, &d->backRef, errorPtr);
if (*errorPtr > SEVERE)
return NULL;
else if (p[0] != ')' && p[0] != ']' && p[0] != ',')
/* missing terminator */
{
NEWERROR(*errorPtr, SYNTAX);
return NULL;
}
else
switch (scale)
{
case 1: return p;
case 2: d->xtenWord |= SCALE_TWO; return p;
case 4: d->xtenWord |= SCALE_FOUR; return p;
case 8: d->xtenWord |= SCALE_EIGHT; return p;
default: NEWERROR(*errorPtr, SYNTAX); return NULL;
}
}
}
/* size not specified, scale specified */
else if (p[2] == '*')
{
p = eval(p+3, &scale, &d->backRef, errorPtr);
if (*errorPtr > SEVERE)
return NULL;
else if (p[0] != ')' && p[0] != ']')
{
NEWERROR(*errorPtr, SYNTAX);
return NULL;
}
else
switch (scale)
{
case 1: return p;
case 2: d->xtenWord |= SCALE_TWO; return p;
case 4: d->xtenWord |= SCALE_FOUR; return p;
case 8: d->xtenWord |= SCALE_EIGHT; return p;
default: NEWERROR(*errorPtr, SYNTAX); return NULL;
}
}
else /* neither ')', nor '.', nor '*' follows Xn */
{
NEWERROR(*errorPtr, SYNTAX);
return NULL;
}
}
else /* incorrect indexing syntax */
return NULL;
}
char *opParse(char *p, opDescriptor *d, int *errorPtr)
{
char *t; /* temporary pointers */
long value;
char ref;
int error;
d->xtenWord = 0; /* initialize */
/**********************************************************\
***** data or address register direct: *****
***** "Dn" or "An" *****
\**********************************************************/
if (isRegNum(p[1]) && isTerm(p[2]))
{
if (p[0] == 'D')
{
d->mode = DnDirect;
d->reg = p[1] - '0';
return (p + 2);
}
else if (p[0] == 'A')
{
d->mode = AnDirect;
d->reg = p[1] - '0';
return (p + 2);
}
}
/**********************************************************\
***** Stack Pointer (A7) direct: *****
***** "SP" *****
\**********************************************************/
if (p[0] == 'S' && p[1] == 'P' && isTerm(p[2]))
{
d->mode = AnDirect;
d->reg = 7;
return (p + 2);
}
/**********************************************************\
***** Address register indirect: *****
***** "(An)", "(An)+", "(SP)", or "(SP)+" *****
\**********************************************************/
if (p[0] == '('
&& ((p[1] == 'A' && isRegNum(p[2]))
|| (p[1] == 'S' && p[2] == 'P'))
&& p[3] == ')')
{
if (p[1] == 'S')
d->reg = 7;
e